package com.education.welco.controller;

import com.education.common.pojo.AjaxResult;
import com.education.common.utils.ApiReturnObject;
import com.education.common.utils.StringUtils;
import com.education.utils.*;
import com.education.welco.enums.FileTypeEnum;
import com.education.welco.pojo.PlatformResources;
import com.education.welco.pojo.dto.FileUploadDTO;
import com.education.welco.pojo.vo.DirTreeNode;
import com.education.welco.pojo.vo.PathNodeVO;
import com.education.welco.pojo.vo.PlatformResourcesVo;
import com.education.welco.service.IPlatformResourcesService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

import static com.education.welco.pojo.consts.FileConst.*;

/**
 * 平台资源 controller业务
 *
 * @Author: liftsail
 * @Date: 2022-09-14
 * @Description: 不积跬步无以至千里
 */
@RestController
@RequestMapping("/platformResources")
@Validated
public class PlatformResourcesController {

    @Autowired
    private IPlatformResourcesService platformResourcesService;
    @Autowired
    private BaiduAipContentCensor baiduAipContentCensor;

    /**
     * 列表查询平台资源
     */
    @GetMapping("/list")
    public ApiReturnObject list(PlatformResources platformResources, Integer pageNum, Integer pageSize) {
        if (pageNum != null && pageSize != null) {
            PageHelper.startPage(pageNum, pageSize);
        }
        List<PlatformResources> list = platformResourcesService.selectPlatformResourcesList(platformResources);
        PageInfo pageInfo = new PageInfo<>(list);
        return new ApiReturnObject("200", "查询成功", pageInfo);
    }


    /**
     * 新增保存平台资源
     */
    @PostMapping("/add")
    public ApiReturnObject addSave(@RequestBody PlatformResources platformResources) {
        platformResourcesService.insertPlatformResources(platformResources);
        return new ApiReturnObject("200", "添加成功", "");
    }


    /**
     * 主键详情平台资源
     */
    @GetMapping("/selectOne")
    public ApiReturnObject selectOne(Integer id) {
        PlatformResources result = platformResourcesService.selectPlatformResourcesById(id);
        return new ApiReturnObject("200", "查询成功", result);
    }

    /**
     * 修改保存平台资源
     */
    @PostMapping("/update")
    public ApiReturnObject editSave(@RequestBody PlatformResources platformResources) {
        platformResourcesService.updatePlatformResources(platformResources);
        return new ApiReturnObject("200", "修改成功", "");
    }

    /**
     * 删除平台资源
     */
    @PostMapping("/del")
    public ApiReturnObject remove(String ids) {
        //todo 删除前进行逻辑判断(星标、共享)
        platformResourcesService.deletePlatformResourcesByIds(ids);
        return new ApiReturnObject("200", "删除成功", "");
    }

    /**
     * 新建文件夹
     *
     * @param platformResources
     * @return
     */
    @PostMapping(value = "/mkdir")
    public ApiReturnObject mkdir(@RequestBody PlatformResources platformResources) {
        platformResourcesService.mkdir(platformResources.getUserId(), platformResources.getPid(), platformResources.getFileName());
        return new ApiReturnObject("200", "目录创建成功！", "");
    }

    /**
     * 新增文件/批量操作
     *
     * @param fileUploadDTOList
     * @return
     */
    @PostMapping(value = "/mkfile")
    public ApiReturnObject mkfile(@RequestBody List<FileUploadDTO> fileUploadDTOList) {
        //Long userId, String fileName, String extension, String pid, Long fileSize, String fileUrl
        //遍历
        for (FileUploadDTO fileUploadDTO : fileUploadDTOList) {
            String extension = fileUploadDTO.getFileName().substring(fileUploadDTO.getFileName().lastIndexOf(".") + 1);
            String fileName = fileUploadDTO.getFileName().replace("." + extension, "");
            fileUploadDTO.setFileName(fileName);
            fileUploadDTO.setExtension(extension);
            fileUploadDTO.setFileUrl(fileUploadDTO.getFileUrl());
            platformResourcesService.mkFile(fileUploadDTO);
            //调用内容审核异步方法
            if (!judgeResType(fileUploadDTO.getExtension()).equals("3"))
                baiduAipContentCensor.singleFileAddSave(fileUploadDTO.getFileUrl(), "platform_resources", judgeResType(fileUploadDTO.getExtension()));
        }

        return new ApiReturnObject("200", "文件新增成功！", "");
    }

    //根据文件后缀判断资源类型
    public String judgeResType(String extension) {
        //        1
        if (IMG_FILE.contains(extension)) return "1";
        //        2
        if (VIDEO_FILE.contains(extension)) return "2";
        //        3
        if (DOC_FILE.contains(extension)) return "3";
        return "0";
    }

    /**
     * 提供父目录和分页数据，返回该文件夹下的这些数据
     *
     * @param pageNum
     * @param pageSize
     * @param pid
     * @return
     */
    @GetMapping(value = "/listDir")
    public ApiReturnObject getFileListOldAll(@Length(min = 32, max = 32) @RequestParam(required = false) String pid,
                                             @NotNull @RequestParam(required = false) Long userId,
                                             @NotNull Integer pageNum,
                                             @NotNull Integer pageSize) {
        PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(userId, pid, pageNum, pageSize);
        return new ApiReturnObject("200", "目录文件查询成功！", fileListPage);
    }

    /**
     * 保留文件层级关系同时要筛选文件类型
     * 提供父目录和分页数据，返回该文件夹下的这些数据
     *
     * @param pageNum
     * @param pageSize
     * @param pid
     * @return
     */
    @GetMapping(value = "/listDirForNet2Filter")
    public ApiReturnObject listDirForNet2Filter(@Length(min = 32, max = 32) @RequestParam(required = false) String pid,
                                                @NotNull @RequestParam(required = false) Long userId,
                                                @RequestParam(value = "fileType", required = false) FileTypeEnum fileType,
                                                @NotNull Integer pageNum,
                                                @NotNull Integer pageSize) {
        //PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(null, pid, pageNum, pageSize);
        PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(null, pid, null, null);
        //过滤不满足文件后缀的文件   IMG_FILE   VIDEO_FILE   DOC_FILE
        Set<String> suffixSet = new HashSet<>();
        if (fileType == FileTypeEnum.IMAGE) {
            suffixSet.addAll(IMG_FILE);
        } else if (fileType == FileTypeEnum.VIDEO) {
            suffixSet.addAll(VIDEO_FILE);
        } else if (fileType == FileTypeEnum.DOC) {
            suffixSet.addAll(DOC_FILE);
        }
        List<PlatformResources> collect = fileListPage.getList().parallelStream().filter(platformResources -> platformResources.getIsDir() || suffixSet.contains(platformResources.getExtension())).collect(Collectors.toList());
        PageUtilSimilar pageUtil = new PageUtilSimilar();
        pageUtil.pageUtil(pageNum, pageSize, collect);
        //fileListPage = new PageInfo<>(collect);
        return new ApiReturnObject("200", "目录文件查询成功！", pageUtil);
    }


    /**
     * 提供父目录和分页数据，返回该文件夹下的这些数据(集模糊搜索、文件类型于一身)
     *
     * @param pageNum
     * @param pageSize
     * @param pid
     * @return
     */
    @GetMapping(value = "/listDirForNameAndType")
    public ApiReturnObject getFileList(@Length(min = 32, max = 32) @RequestParam(required = false) String pid,
                                       @NotNull @RequestParam(required = false) Long userId,
                                       @RequestParam(value = "fileName", required = false) String fileName,
                                       @RequestParam(value = "fileType", required = false) FileTypeEnum fileType,
                                       @NotNull Integer pageNum,
                                       @NotNull Integer pageSize) {

        //名字和后缀
        if (fileType != null && StringUtils.isNotEmpty(fileName)) {
            Set<String> extensionSet = FileUtils.getFileExtensionsByType(fileType);
            //文件类型关于in|not in的判断
            Boolean inOrNot = true;
            if (fileType == FileTypeEnum.OTHER) {
                inOrNot = false;
            }
            //    todo 名字和后缀
            List<PlatformResources> platformResourcesList = platformResourcesService.listTheDirByNameAndType(userId, fileName, extensionSet, inOrNot, pid, pageNum, pageSize);
            PageInfo<PlatformResources> platformResourcesPageInfo = new PageInfo<>(platformResourcesList);
            return new ApiReturnObject("200", "目录文件查询成功！", platformResourcesPageInfo);
        }
        if (fileType != null) {
            //文件类型
            if (fileType == FileTypeEnum.ALL) {
                //没条件
                PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(userId, pid, pageNum, pageSize);
                return new ApiReturnObject("200", "目录文件查询成功！", fileListPage);
            }
            PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheTypeFile(userId, fileType, pageNum, pageSize);
            return new ApiReturnObject("200", "文件类型搜索成功！", fileListPage);
        } else if (StringUtils.isNotEmpty(fileName)) {
            //    文件名搜索
            PageInfo<PlatformResources> fileListPage = platformResourcesService.searchFile(fileName, userId, pageNum, pageSize);
            return new ApiReturnObject("200", "模糊搜索文件名成功！", fileListPage);
        } else {
            //没条件
            PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(userId, pid, pageNum, pageSize);
            return new ApiReturnObject("200", "目录文件查询成功！", fileListPage);
        }

        //PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheDir(null, pid, pageNum, pageSize);
        //return new ApiReturnObject("200", "目录文件查询成功！", fileListPage);
    }


    /**
     * 文件搜索-模糊搜索文件名
     *
     * @param fileName
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping(value = "/search")
    public ApiReturnObject searchFile(@NotBlank String fileName,
                                      @NotNull Long userId,
                                      @NotNull Integer pageNum,
                                      @NotNull Integer pageSize) {
        PageInfo<PlatformResources> fileListPage = platformResourcesService.searchFile(fileName, userId, pageNum, pageSize);
        return new ApiReturnObject("200", "模糊搜索文件名成功！", fileListPage);
    }

    /**
     * 获取某一类型文件，例如图片、视频、文档等
     *
     * @param fileType
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping(value = "/list/type")
    public ApiReturnObject getFileListByType(@NotNull FileTypeEnum fileType,
                                             @NotNull Long userId,
                                             @NotNull Integer pageNum,
                                             @NotNull Integer pageSize) {
        PageInfo<PlatformResources> fileListPage = platformResourcesService.listTheTypeFile(userId, fileType, pageNum, pageSize);
        return new ApiReturnObject("200", "文件类型搜索成功！", fileListPage);
    }


    /**
     * 父节点列表-用于显示父路径，字典key为文件id
     *
     * @return
     */
    @GetMapping(value = "/path/tree")
    public AjaxResult getPathTree(@NotNull(message = "userId不能为空") @RequestParam("userId") Long userId) {

        userId = 1L;
        Map<String, PathNodeVO> pathTreeMap = platformResourcesService.getPathTreeMap(userId);
        return AjaxResult.success(pathTreeMap);
    }

    /**
     * 学校资源目录树的接口编写
     * 父节点列表-用于显示父路径，字典key为文件id
     *
     * @return
     */
    @GetMapping(value = "/path/tree/school")
    /*@GetMapping(value = "/path/tree")
    public AjaxResult getPathTree(@NotNull(message = "userId不能为空") @RequestParam("userId") Long userId) {*/
    public AjaxResult getPathTreeForSchooolRes(@NotNull(message = "schoolId不能为空") @RequestParam("schoolId") Integer schoolId) {
        Long userId = 1L;
        Map<String, PathNodeVO> pathTreeMap = platformResourcesService.getPathTreeForSchooolRes(userId, schoolId);
        return AjaxResult.success(pathTreeMap);
    }

    /**
     * 文件移动的时候需要用到该接口，用来展示目录树
     *
     * @param userId
     * @return
     */
    @GetMapping(value = "/dir/tree")
    public ApiReturnObject getDirTree(@NotNull Long userId) {
        DirTreeNode tree = platformResourcesService.dirTree(userId);
        return new ApiReturnObject("200", "目录树搜索成功！", tree);
    }

    //    文件移动实现

    /**
     * 移动文件
     * <p>
     * //* @param  移动文件id
     * //* @param    目标文件夹id(可以是根目录)
     *
     * @return
     */
    @PostMapping(value = "/move")
    //public AjaxResult move(@NotBlank @Length(min = 32, max = 32) String from, @Length(min = 32, max = 32) @RequestParam(required = false) String to) {
    public AjaxResult move(@RequestBody PlatformResourcesVo platformResourcesVo) {

        AjaxResult ajaxResult = platformResourcesService.move(platformResourcesVo.getFrom(), platformResourcesVo.getTo());
        return ajaxResult;
    }

    /**
     * 批量移动文件
     * <p>
     * //* @param from 移动文件id列表         from: 205148e8529440b69f53ecb95e2e0d00,c8673c59468c421eb92d51b97135e9c4
     * //* @param to   目标文件夹id(可以是根目录)
     *
     * @return
     */
    @PostMapping(value = "/batch/move")
    //public AjaxResult batchMove(@RequestParam(value = "from") @NotEmpty List<String> from, @Length(min = 32, max = 32) @RequestParam(required = false) String to) {
    public AjaxResult batchMove(@RequestBody PlatformResourcesVo platformResourcesVo) {

        AjaxResult ajaxResult = platformResourcesService.move(platformResourcesVo.getFromList(), platformResourcesVo.getTo());
        return ajaxResult;
    }


    /**
     * 重命名文件名和扩展名
     * <p>
     * //* @param id    文件id
     * //* @param fileName  文件基础名
     * //* @param extension 文件扩展名
     *
     * @return
     */
    @PostMapping(value = "/rename")
    //public AjaxResult rename(@NotBlank @Length(min = 32, max = 32) String fileId,
    //                         @NotBlank String filename,
    //                         @RequestParam(required = false) String extension) {
    public AjaxResult rename(@RequestBody PlatformResourcesVo platformResourcesVo) {
        platformResourcesService.rename(platformResourcesVo.getId(), platformResourcesVo.getFileName(), platformResourcesVo.getExtension());
        return AjaxResult.success("文件重命名成功！");
    }


    /**
     * 文件设置备注名称
     * <p>
     * //* @param id     文件id
     * //* @param fileRemark 文件备注名称
     *
     * @return
     */
    @PostMapping(value = "/remark")
    //public AjaxResult remark(@NotBlank @Length(min = 32, max = 32) String fileId,
    //                         @NotBlank String fileRemark) {
    public AjaxResult remark(@RequestBody PlatformResourcesVo platformResourcesVo) {
        int i = platformResourcesService.remark(platformResourcesVo.getId(), platformResourcesVo.getRemark());
        return AjaxResult.success("文件添加备注成功！");
    }


    /**
     * 文件批量设置备注名称
     * <p>
     * //* @param idList 文件id集合
     * //* @param fileRemark 文件备注名称
     *
     * @return
     */
    @PostMapping(value = "/batch/remark")
    //public AjaxResult batchRemark(@RequestParam("fileIdList") @NotEmpty List<String> fileIdList,
    //                              @NotBlank String fileRemark) {
    public AjaxResult batchRemark(@RequestBody PlatformResourcesVo platformResourcesVo) {
        int i = platformResourcesService.remark(platformResourcesVo.getIdList(), platformResourcesVo.getRemark());
        return AjaxResult.success("文件批量添加备注成功！");
    }

    //    删除以及批量删除的实现

    /**
     * 删除文件或文件夹
     *
     * @param platformResourcesVo 文件id
     * @return
     */
    @PostMapping(value = "/delete")
    public AjaxResult delete(@RequestBody PlatformResourcesVo platformResourcesVo) {
        platformResourcesService.delete(platformResourcesVo.getId());
        return AjaxResult.success("删除成功！");
    }

    /**
     * 批量删除文件或文件夹
     *
     * @param platformResourcesVo 文件id列表-idList
     * @return
     */
    @PostMapping(value = "/batch/delete")
    public AjaxResult batchDelete(@RequestBody PlatformResourcesVo platformResourcesVo) {
        platformResourcesService.delete(platformResourcesVo.getIdList());
        return AjaxResult.success("批量删除成功！");
    }


    @PostMapping(value = "/batch/downzip")
    public void downloadZipHttpByDataStream(HttpServletResponse response, HttpServletRequest request,
                                            @RequestBody List<FileUploadDTO> fileUploadDTOList) {
        List<Map<String, String>> mapList = new ArrayList<>();
        //String urlStr = "https://code.jquery.com/jquery-3.6.0.js";

        for (FileUploadDTO fileUploadDTO : fileUploadDTOList) {
            Map<String, String> map = new HashMap<>();
            map.put("path", fileUploadDTO.getFileUrl());
            map.put("name", fileUploadDTO.getFileName() + "." + fileUploadDTO.getExtension());
            mapList.add(map);
        }

        //将网络url资源文件的多个文件打包成压缩包并输出流下载
        FileUtil.zipUrlToFile(mapList, request, response);

        // 浏览器访问：http://x.x.x.x/test/down/zip/http
    }


    @GetMapping(value = "/downSingle")
    public void downloadFileHttpStream(HttpServletResponse response, HttpServletRequest request,
                                       @RequestParam String fileName,
                                       @RequestParam String fileUrl) {
        /*// 文件网络地址
        String urlStr = "https://code.jquery.com/jquery-3.6.0.js";
        // 文件名称
        String fileName = "jquery.js";
        //下载http文件流
        FileUtil.downloadHttpFile(urlStr, request, response, fileName);*/
        FileUtil.downloadHttpFile(fileUrl, request, response, fileName);

        // 浏览器访问：http://localhost:8082/singleFileHttp/down
    }

}